In catching a std::bad_alloc exception, you actually caught an object of class
std::bad_alloc thrown by new. std::bad_alloc is a class that inherits from C++ standard class std::exception , declared in header <exception>.
Class std::exception that is the base class supports a useful and important virtual
method what() that gives a more descriptive reason on the nature of the problem causing the exception.
You can make use of std::exception being a base class for many exceptions types and create one catch(const exception&) that can catch all exceptions that have std::exception as base:
void someFunc()
{
try
{
// code made exception safe
}
catch (const std::exception& exp) // catch bad_alloc, bad_cast, etc
{
std::cerr << “Exception encountered: “ << exp.what() << std::endl;
}
}
You can throw an exception of whatever type you want. But, there is a benefit in inheriting from std::exception: all existing exception handlers that catch(const std::exception&) and work for bad_alloc , bad_cast and the like will automatically scale up to catch your new exception class as well because it has the base class in common with them.
# include <iostream> // std::cout, std::endl
# include <string> // std::string
# include <exception> // std::exception
class CustomException: public std::exception
{
private:
std::string reason;
public:
// constructor of an exception
CustomException(const char* why) : reason(why) {}
~CustomException() throw() {}
// redefining virtual function to return ‘reason’
virtual const char* what() const throw()
{
return reason.c_str();
}
};
double divide(double a, double b)
{
if(b == 0)
throw CustomException("CustomException: Cant divide by 0");
return (a / b);
}
int main()
{
try
{
std::cout << "Result of division is: " << divide(12, 0);
}
catch(std::exception& exp)// catch CustomException, bad_alloc, etc
{
std::cerr << "Exception: " << exp.what() << std::endl;
}
return 0;
}